#include "BondDealMatrix.h"
#include "BondDealMatrixData.h"
#include "BondDealProfile.h"
#include "../StringResource.h"
#include <bondlib/BondContainer.h>
#include <bondlib/BondDeal/PanoramicBondDealContainer.h>
#include <core/FileSys.h>
#include <core/QbLogger.h>
#include <uam/ServerTimeMgr.h>
#include <QSettings>

#define FIXED_MATRIX_MAX_TERM          60000  //锟斤拷锟斤拷锟斤拷锟街?

/// <summary>
/// /////////////////////////////////////////////////////////////////////////
/// </summary>
BondDealMatrixData::BondDealMatrixData()
	:m_dealType(BondDealMatrix::eWndTypeFixedIncome)
{
}

BondDealMatrixData::~BondDealMatrixData()
{
}

void BondDealMatrixData::clearBondData()
{
	log_debug("fixed screen initial bond");
	m_mapCell.clear();
}

int BondDealMatrixData::getCellIndex(int nType, int row, int col)
{
	return nType * 10000 + row * 100 + col;
}

int BondDealMatrixData::getCellType(int cell)
{
	return cell / 10000;
}

int BondDealMatrixData::getCellRow(int cell)
{
	return (cell % 10000) / 100;
}

int BondDealMatrixData::getCellCol(int cell)
{
	return cell % 100;
}

void BondDealMatrixData::saveTextAndChartType(int textShowType, int chartShowType)
{
	m_textType = textShowType;
	m_chartType = chartShowType;
}

int BondDealMatrixData::textShowType() const
{
	return m_textType;
}

int BondDealMatrixData::chartShowType() const
{
	return m_chartType;
}

void BondDealMatrixData::setTextShowType(int v)
{
	m_textType = v;
}

void BondDealMatrixData::setChartShowType(int v)
{
	m_chartType = v;
}

void BondDealMatrixData::reloadBondData()
{
#define _load_deal(type)\
{\
	int eType = type;\
	auto& mapBond = dealMap.getBondDeal(eType);\
	for (auto itBond : mapBond)\
	{\
		int bondIndex = itBond.first;\
		if (!bc.IsValidIndex(bondIndex))continue;\
		bool ytm = eType == panoramic::bondType_credit ? itBond.second.m_bytm : false;\
		setResult.clear();\
		if (!getBondCellKey(eType, bondIndex, ytm, setResult))continue;\
		for (auto cell : setResult)\
		{\
			const auto& itCell = m_mapCell.find(cell);\
			if (itCell == m_mapCell.end())\
			{\
				BondDealMatrixCellData cdata;\
				cdata.m_bondIndex = bondIndex;\
				cdata.m_dealCount = itBond.second.m_count;\
				cdata.m_lastUpdate = itBond.second.m_lastUpdate;\
				m_mapCell.insert(make_pair(cell, cdata));\
			}\
			else\
			{\
				if ((itBond.second.m_count > itCell->second.m_dealCount) ||\
					(itBond.second.m_count == itCell->second.m_dealCount && itBond.second.m_lastUpdate > itCell->second.m_lastUpdate))\
				{\
					itCell->second.m_bondIndex = bondIndex;\
					itCell->second.m_dealCount = itBond.second.m_count;\
					itCell->second.m_lastUpdate = itBond.second.m_lastUpdate;\
				}\
			}\
		}\
	}\
}
	//DETAIL_TEST(_T("BONDDATA--------"));
	clearBondData();
	static std::set<int> setResult;
	SCOPED_LOCK(CPanoramicBondDealContainer::instance().GetLock());
	CPanoramicBondDealMap& dealMap = CPanoramicBondDealContainer::instance().GetDealMap();
	if (m_dealType == BondDealMatrix::eWndTypeFixedIncome) {
		CBondContainer& bc = CBondContainer::instance();
		_load_deal(panoramic::bondType_interest);
		_load_deal(panoramic::bondType_credit);
		_load_deal(panoramic::bondType_ncd);
	}
	log_debug("fixed screen Reload Bond Data锟斤拷");
}

bool BondDealMatrixData::updateBondData(QList<xQBPanoramicMarketStreamUnit>& lstData, std::map<int, int>& mapResult)
{
	if (lstData.size() <= 0)return false;

	static std::set<int> setResult;
	SCOPED_LOCK(CPanoramicBondDealContainer::instance().GetLock());
	CPanoramicBondDealMap& dealMap = CPanoramicBondDealContainer::instance().GetDealMap();
	CBondContainer& bc = CBondContainer::instance();
	if (m_dealType == BondDealMatrix::eWndTypeFixedIncome) {
		for (auto& it : lstData)
		{
			int bondIndex = bc.GetBondIndex(it.m_bondkey, it.m_listedmarket);
			if (!bc.IsValidIndex(bondIndex))continue;
			const BondDealInfo& bdInfo = dealMap.getDealInfo(bondIndex);
			const CBondInfo& bi = bc.ElementAtR(bondIndex);
			int eType;
			if (bi.is_interest_bond())
				eType = panoramic::bondType_interest;
			else if (bi.is_credit_bond())
				eType = panoramic::bondType_credit;
			else if (bi.IsBondNCD())
				eType = panoramic::bondType_ncd;
			else continue;

			setResult.clear();

			bool ytm = (eType == panoramic::bondType_credit ? (it.m_exercise[0] == '1') : false);
			if (!getBondCellKey(eType, bondIndex, ytm, setResult))continue;
			for (auto cell : setResult)
			{
				const auto& itCell = m_mapCell.find(cell);
				if (itCell == m_mapCell.end())
				{
					BondDealMatrixCellData cdata;
					cdata.m_bondIndex = bondIndex;
					cdata.m_dealCount = bdInfo.m_count;
					cdata.m_lastUpdate = bdInfo.m_lastUpdate;
					m_mapCell.insert(make_pair(cell, cdata));
					mapResult.insert(make_pair(cell, bondIndex));
				}
				else
				{
					if ((bdInfo.m_count > itCell->second.m_dealCount) ||
						(bdInfo.m_count == itCell->second.m_dealCount && bdInfo.m_lastUpdate > itCell->second.m_lastUpdate))
					{
						itCell->second.m_bondIndex = bondIndex;
						itCell->second.m_dealCount = bdInfo.m_count;
						itCell->second.m_lastUpdate = bdInfo.m_lastUpdate;
						mapResult.insert(make_pair(cell, bondIndex));
					}
					else if (bdInfo.m_count < itCell->second.m_dealCount)
					{
						if (bondIndex == itCell->second.m_bondIndex)
						{//锟斤拷前锟斤拷删锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟?
							mapResult.insert(make_pair(cell, bondIndex));
						}
						else
						{//格子内容不刷新，仅闪烁
							mapResult.insert(make_pair(cell, -999));
						}
					}
					else
					{//格子内容不刷新，仅闪烁
						mapResult.insert(make_pair(cell, -999));
					}
				}
			}
		}
	}
	return mapResult.size() > 0;
}
//锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟揭讹拷应锟斤拷
bool BondDealMatrixData::getRangeColumn(int nType, int nDays, std::set<int>& setResult)
{
	CBondDealTermRange::emBondType eType = static_cast<CBondDealTermRange::emBondType>(nType - 1);
	map<string, sBondDealTermRgUnit>* pMap = CBondDealTermRange::instance().GetMap(eType);
	if (pMap == nullptr) return false;

	for (map<string, sBondDealTermRgUnit>::iterator itor = pMap->begin(); itor != pMap->end(); ++itor)
	{
		sBondDealTermRgUnit& unit = itor->second;
		if (nDays > unit.m_daysLeft && nDays <= unit.m_daysRight)
		{
			QString str = QString::fromLocal8Bit(unit.m_term);
			int col = getTermExchange(eType, str);
			if (col > 0)
			{
				setResult.insert(col);
			}
		}
	}
	return setResult.size() > 0;
}

int BondDealMatrixData::getTermExchange(CBondDealTermRange::emBondType eType, QString& strTerm)
{
	if (eType == CBondDealTermRange::bondType_Interest && strTerm == "LangTerm")
	{//锟斤拷锟斤拷债 - 锟斤拷锟斤拷
		return CBondDealTermRange::termRg_Interest - 1;
	}
	else if (eType == CBondDealTermRange::bondType_NCD && strTerm == "15D")
	{//NCD - 锟劫碉拷锟斤拷
		return 0;
	}


	for (int col = 1; col < BondDealMatrix::m_MaxCountCount; col++)
	{
		if (eType == CBondDealTermRange::bondType_Interest)
		{
			if (NewStringTable::strBondDealGovHead(col) == strTerm)
			{
				return col;
			}
		}
		if ((eType == CBondDealTermRange::bondType_Credit))
		{
			if (NewStringTable::strBondDealCreditHead(col) == strTerm)
			{
				return col;
			}
		}
		if ((eType == CBondDealTermRange::bondType_NCD))
		{
			if (NewStringTable::strBondDealNCDHead(col) == strTerm)
			{
				return col;
			}
		}
	}
	return 0;
}

bool BondDealMatrixData::getBondCellKey(int eType, int bondIndex, bool ytm, std::set<int>& setResult)
{
	int nType = 0;
	switch (eType)
	{
	case panoramic::bondType_interest: nType = BondDealMatrix::eMTFixedIncomeGov; break;
	case panoramic::bondType_credit: nType = BondDealMatrix::eMTFixedIncomeCredit; break;
	case panoramic::bondType_ncd: nType = BondDealMatrix::eMTFixedIncomeNCD; break;
	default:return false; break;
	}

	auto itInValid = m_setBondInvalid.find(bondIndex);
	if (itInValid != m_setBondInvalid.end())return false;

	auto itFind = m_mapBondFind.find(bondIndex);
	if (itFind != m_mapBondFind.end())
	{
		setResult = itFind->second;
		return true;
	}

	CBondContainer& bcont = CBondContainer::instance();
	const CBondInfo& bondInfo = bcont.ElementAtR(bondIndex);

	int nRow = -1;
	if (eType == panoramic::bondType_interest) {
		if (bondInfo.IsBondCountry()) nRow = BondDealMatrix::eTypeCountry;//锟斤拷债
		else if (bondInfo.IsBondGKZ()) nRow = BondDealMatrix::eTypeCBDBond;//锟斤拷锟斤拷
		else if (strcmp(bondInfo.GetIssuerCode(), "Z000189") == 0 && strcmp(bondInfo.GetBondSubType(), "PSB") != 0) nRow = BondDealMatrix::eTypeEximBank;//锟斤拷锟斤拷
		else if (strcmp(bondInfo.GetIssuerCode(), "Z000207") == 0 && strcmp(bondInfo.GetBondSubType(), "PSB") != 0) nRow = BondDealMatrix::eTypeADBC;//农锟斤拷
		else if (bondInfo.IsBondLocal()) nRow = nRow = BondDealMatrix::eTypeMunicipal;//锟截凤拷债
	}
	else if (eType == panoramic::bondType_credit) {
		CBondDealProFile& bdProfile = CBondDealProFile::instance();
		int nRateAAR = bdProfile.m_mapRate["AA-"];
		QString strRate = QString::fromLocal8Bit(bondInfo.GetIssuerRatingEx()).trimmed();
		if (strRate == "AAA+") {
			nRow = BondDealMatrix::eRateAAAP;
		}
		else
		{
			strRate = QString::fromLocal8Bit(bondInfo.GetIssuerRating()).trimmed();
			if (strRate == "AAA") {
				nRow = BondDealMatrix::eRateAAA;
			}
			else if (strRate == "AA+") {
				nRow = BondDealMatrix::eRateAAP;
			}
			else if (strRate == "AA") {
				nRow = BondDealMatrix::eRateAA;
			}
			else
			{
				if (strcmp(bondInfo.GetBondSubType(), "PSB") != 0)
				{
					auto pos = bdProfile.m_mapRate.find(strRate);
					if (pos != bdProfile.m_mapRate.end() && pos->second <= nRateAAR) {
						nRow = BondDealMatrix::eRateOther;
					}
				}
			}
		}
	}
	else if (eType == panoramic::bondType_ncd) {
		if (strcmp(bondInfo.GetBondSubType(), "MCD") == 0 || strcmp(bondInfo.GetBondSubType(), "SHD") == 0) {//锟斤拷锟斤拷锟斤拷锟斤拷为锟斤拷锟酵伙拷锟竭股凤拷锟斤拷
			nRow = BondDealMatrix::eRateAAAP;  //使锟斤拷AAAP枚锟斤拷值锟斤拷示锟斤拷锟斤拷/锟缴凤拷锟斤拷
		}
		else if (strcmp(bondInfo.GetIssuerRating(), "AAA") == 0) {
			nRow = BondDealMatrix::eRateAAA;
		}
		else if (strcmp(bondInfo.GetIssuerRating(), "AA+") == 0) {
			nRow = BondDealMatrix::eRateAAP;
		}
		else if (strcmp(bondInfo.GetIssuerRating(), "AA") == 0) {
			nRow = BondDealMatrix::eRateAA;
		}
		else {
			nRow = BondDealMatrix::eRateOther;
		}
	}

	if (nRow <= 0)
	{
		m_setBondInvalid.insert(bondIndex);
		return false;
	}

	std::string str = bondInfo.GetRemainPeriod(ServerTimeMgr::instance().serverTime());
	int nRe = (int)CBondContainer::CalcRemainingDay(str, ytm);

// 	if (bReload || m_mapRange.size() <= 0)
// 		loadRangeConfig();  //锟斤拷锟斤拷锟斤拷锟矫碉拷锟斤拷锟斤拷展示锟斤拷片

	static std::set<int> setColumn;
	setColumn.clear();
	if (!getRangeColumn(nType, nRe, setColumn))
	{
		m_setBondInvalid.insert(bondIndex);
		return false;
	}

	for (auto nCol : setColumn)
	{
		int cell = getCellIndex(nType, nRow, nCol);
		setResult.insert(cell);
	}

	m_mapBondFind.insert(make_pair(bondIndex, setResult));
	return true;
}

void BondDealMatrixData::loadRangeConfig()
{
	m_mapRange.clear();
	QSettings settings(FileSys::instance()->writeableAppCfgDir() + "/gszhConfig.ini", QSettings::IniFormat);
	{
		int eType = BondDealMatrix::eMTFixedIncomeGov;
		std::vector<UINT> vctRange;
		settings.beginGroup("fiGovRange");
		for (int i = BondDealMatrix::eGovTerm1Y; i < BondDealMatrix::eGovTermCount; i++)
		{
			QString name = QString("range%1").arg(i);
			switch (i)
			{
			case BondDealMatrix::eGovTerm15Y:
			case BondDealMatrix::eGovTerm20Y:
			case BondDealMatrix::eGovTerm30Y:
			case BondDealMatrix::eGovTerm50Y:
				vctRange.push_back(settings.value(name, 0).toInt());
				break;
			default:
				vctRange.push_back(settings.value(name, 1).toInt());
				break;				
			}
		}
		settings.endGroup();
		int validCount = 0;
		for (int i = 0; i < (int)vctRange.size(); i++)
		{
			if (vctRange[i] == 1)
				validCount++;
		}
		if (validCount == 0)
		{
			for (int i = 0; i < BondDealMatrix::eGovTermCount - 1; i++)
				vctRange[i] = 1;
			vctRange[6] = 0;
			vctRange[7] = 0;
			vctRange[8] = 0;
			vctRange[9] = 0;
		}
		m_mapRange.insert(make_pair(eType, vctRange));
	}
	{
		int eType = BondDealMatrix::eMTFixedIncomeCredit;
		std::vector<UINT> vctRange;
		settings.beginGroup("fiGreditRange");
		for (int i = BondDealMatrix::eCreditTerm1M; i < BondDealMatrix::eCreditTermCount; i++)
		{
			QString name = QString("range%1").arg(i);
			switch (i)
			{
			case BondDealMatrix::eCreditTerm1M:
			case BondDealMatrix::eCreditTerm3M:
			case BondDealMatrix::eCreditTerm7Y:
			case BondDealMatrix::eCreditTerm10Y:
				vctRange.push_back(settings.value(name, 0).toInt());
				break;
			default:
				vctRange.push_back(settings.value(name, 1).toInt());
				break;

			}
		}
		settings.endGroup();
		int validCount = 0;
		for (int i = 0; i < (int)vctRange.size(); i++)
		{
			if (vctRange[i] == 1)
				validCount++;
		}
		if (validCount == 0)
		{
			for (int i = 0; i < BondDealMatrix::eCreditTermCount - 1; i++)
				vctRange[i] = 1;
			vctRange[0] = 0;
			vctRange[1] = 0;
			vctRange[8] = 0;
			vctRange[9] = 0;
		}
		m_mapRange.insert(make_pair(eType, vctRange));
	}
	{
		int eType = BondDealMatrix::eMTFixedIncomeNCD;
		std::vector<UINT> vctRange;
		settings.beginGroup("fiNCDRange");
		for (int i = BondDealMatrix::eNCDTerm15D; i < BondDealMatrix::eNCDTermCount; i++)
		{
			QString name = QString("range%1").arg(i);
			switch (i)
			{
			case BondDealMatrix::eNCDTerm15D:
				vctRange.push_back(settings.value(name, 0).toInt());
				break;
			default:
				vctRange.push_back(settings.value(name, 1).toInt());
				break;

			}
		}
		settings.endGroup();
		int validCount = 0;
		for (int i = 0; i < (int)vctRange.size(); i++)
		{
			if (vctRange[i] == 1)
				validCount++;
		}
		if (validCount == 0)
		{
			for (int i = 0; i < BondDealMatrix::eNCDTermCount - 1; i++)
			{
				vctRange[i] = 1;
			}
			vctRange[0] = 0;
		}
		m_mapRange.insert(make_pair(eType, vctRange));
	}
}

int BondDealMatrixData::getCellData(int nType, int row, int col)
{
	int index = getCellIndex(nType, row, col);
	if (m_mapCell.find(index) == m_mapCell.end())return -1;

	return m_mapCell[index].m_bondIndex;
}